package player_queues

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlc"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"strings"
)

var _ PlayerQueuesModel = (*customPlayerQueuesModel)(nil)

type (
	// PlayerQueuesModel is an interface to be customized, add more methods here,
	// and implement the added methods in customPlayerQueuesModel.
	PlayerQueuesModel interface {
		playerQueuesModel
		InsertTranCtx(ctx context.Context, sesstion sqlx.Session, data *PlayerQueues) (sql.Result, error)
		Find(ctx context.Context, playercode sql.NullString) (*PlayerQueues, error)
		FindByPlayercode(ctx context.Context, playercode sql.NullString) (*PlayerQueues, error)
		FindPlayerQueues(ctx context.Context, pageIndex, pageSize int64) ([]*PlayerQueues, error)
		FindTotalCount(ctx context.Context) (int64, error)
		FindQueuesContainerGroups(ctx context.Context, cardno, deptid, roomid string) ([]*PlayerQueueModel, error)
		FindQueuesContainerGroupsByGroupId(ctx context.Context, groupid []interface{}) ([]*PlayerQueueModel, error)
		FindQueuesContainerGroupsByRegNo(ctx context.Context, regNo string) (*PlayerQueueModel, error)
	}

	customPlayerQueuesModel struct {
		*defaultPlayerQueuesModel
	}
)

// NewPlayerQueuesModel returns a model for the database table.
func NewPlayerQueuesModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) PlayerQueuesModel {
	return &customPlayerQueuesModel{
		defaultPlayerQueuesModel: newPlayerQueuesModel(conn, c, opts...),
	}
}

func (c customPlayerQueuesModel) Find(ctx context.Context, playercode sql.NullString) (*PlayerQueues, error) {
	//TODO implement me
	return nil, nil
}

// InsertTranCtx 事务插入
func (c customPlayerQueuesModel) InsertTranCtx(ctx context.Context, sesstion sqlx.Session, data *PlayerQueues) (sql.Result, error) {
	query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", c.table, playerQueuesRowsExpectAutoSet)
	return sesstion.ExecCtx(ctx, query, data.Playercode, data.Groupid, data.Patientid, data.Patientname, data.Gender, data.Cardno, data.Seq, data.Serialnumber, data.Sort, data.Deptid, data.Deptname, data.Roomid, data.Roomname, data.Doctorid, data.Doctorname, data.Callcount, data.State, data.Statelist, data.Preengagemode, data.Wiget, data.Registerway, data.Ismake, data.Registertype, data.Playeridentity, data.Startseattime, data.Endseattime, data.Updatetime, data.Createtime)
}

// FindByPlayercode 不使用缓存,不然可能会没有同步的情况,已经在队列中了,重复签时出错(还会再次插入信息到队列表中,playercode 唯一报错)
func (m *defaultPlayerQueuesModel) FindByPlayercode(ctx context.Context, playercode sql.NullString) (*PlayerQueues, error) {
	var resp PlayerQueues
	query := fmt.Sprintf("select %s from %s where `playercode` = ? limit 1", playerQueuesRows, m.table)
	err := m.QueryRowNoCache(&resp, query, playercode.String)

	switch err {
	case nil:
		return &resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

// FindPlayerQueues 分页查询队列信息
func (m *defaultPlayerQueuesModel) FindPlayerQueues(ctx context.Context, pageIndex, pageSize int64) ([]*PlayerQueues, error) {
	var page = (pageIndex - 1) * pageSize
	var resp []*PlayerQueues
	query := fmt.Sprintf("select %s from %s limit ?,?", playerQueuesRows, m.table)
	err := m.QueryRowsNoCache(&resp, query, page, pageSize)

	switch err {
	case nil:
		return resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

type PlayerQueueCount struct {
	Count sql.NullInt64 `db:"count"`
}

// FindTotalCount 查找总条数
func (m *defaultPlayerQueuesModel) FindTotalCount(ctx context.Context) (int64, error) {
	var resp PlayerQueueCount
	query := fmt.Sprintf("select count(*) as count from %s", m.table)
	err := m.QueryRowNoCache(&resp, query)
	if err != nil {
		return 0, err
	}
	return resp.Count.Int64, nil
}

// FindQueuesContainerGroups 查询所有信息,包含队列组信息
func (m *defaultPlayerQueuesModel) FindQueuesContainerGroups(ctx context.Context, cardno, deptid, roomid string) ([]*PlayerQueueModel, error) {
	var resp []*PlayerQueueModel
	query := fmt.Sprintf("SELECT qg.name as groupname,p.id,qg.id as groupid,patientid,patientname,playercode,deptid,deptname,roomid,roomname,gender,cardno,seq,serialnumber,sort,doctorid,doctorname,callcount,p.state,statelist,wiget,registertype,ismake,registertype,playeridentity,startseattime,endseattime,createtime FROM callsystem.player_queues p,callsystem.group_items gi,callsystem.queue_groups qg where p.groupid=qg.id and qg.id=gi.groupid and p.cardno like ? and (deptid like ? or deptid is null) and (roomid like ? or roomid is null)")
	err := m.QueryRowsNoCache(&resp, query, "%"+cardno+"%", "%"+deptid+"%", "%"+roomid+"%")
	switch err {
	case nil:
		return resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

// FindQueuesContainerGroupsByGroupId 查询所有信息,包含队列组信息
func (m *defaultPlayerQueuesModel) FindQueuesContainerGroupsByGroupId(ctx context.Context, groupids []interface{}) ([]*PlayerQueueModel, error) {
	placeholderStr := m.placeholders(len(groupids))
	var resp []*PlayerQueueModel
	query := fmt.Sprintf(`SELECT qg.name as groupname,qg.starttime as starttime,qg.endtime endtime, p.id,qg.id as groupid,patientid,patientname,playercode,dept.deptid,dept.deptname,
								roomid,roomname,gender,cardno,seq,serialnumber,sort,doctorid,doctorname,callcount,p.state,statelist,
								p.wiget,registertype,ismake,registertype,playeridentity,startseattime,endseattime,p.createtime 
								FROM callsystem.player_queues p,
								callsystem.group_items gi,
								callsystem.queue_groups qg, 
								depts dept 
								where p.groupid=gi.id 
								and qg.id=p.groupid  
								and p.deptid=dept.deptid
								and p.groupid in (%s)`, placeholderStr)
	//query := fmt.Sprintf("SELECT qg.name as groupname,p.id,qg.id as groupid,patientid,patientname,playercode,deptid,deptname,roomid,roomname,gender,cardno,seq,serialnumber,sort,doctorid,doctorname,callcount,p.state,statelist,wiget,registertype,ismake,registertype,playeridentity,startseattime,endseattime,createtime FROM callsystem.player_queues p,callsystem.group_items gi,callsystem.queue_groups qg where p.groupid=gi.id and qg.id=p.groupid  and p.groupid in (%s)", placeholderStr)
	err := m.QueryRowsNoCache(&resp, query, groupids...)
	switch err {
	case nil:
		return resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}

// FindQueuesContainerGroupsByRegNo 查询所有信息,包含队列组信息
func (m *defaultPlayerQueuesModel) FindQueuesContainerGroupsByRegNo(ctx context.Context, regNo string) (*PlayerQueueModel, error) {
	var resp PlayerQueueModel
	query := fmt.Sprintf("SELECT qg.name as groupname,p.id,qg.id as groupid,patientid,patientname,playercode,deptid,deptname,roomid,roomname,gender,cardno,seq,serialnumber,sort,doctorid,doctorname,callcount,p.state,statelist,wiget,registertype,ismake,registertype,playeridentity,startseattime,endseattime,createtime FROM callsystem.player_queues p,callsystem.group_items gi,callsystem.queue_groups qg where p.groupid=gi.id and qg.id=p.groupid and p.playercode=?")
	err := m.QueryRowNoCache(&resp, query, regNo)
	switch err {
	case nil:
		return &resp, nil
	case sqlc.ErrNotFound:
		return nil, ErrNotFound
	default:
		return nil, err
	}
}
func (m *defaultPlayerQueuesModel) placeholders(n int) string {
	var b strings.Builder
	for i := 0; i < n-1; i++ {
		b.WriteString("?,")
	}
	if n > 0 {
		b.WriteString("?")
	}
	return b.String()
}
